
#ifndef __MESH_H__
#define __MESH_H__

#include <d3d9.h>
#include <d3dx9math.h>
#include <vector>

#include "Vertex.h"
#include "Triangle.h"
#include "Quad.h"

using namespace std;
class BBox;
class Entity;

enum TexCoordType { RECTANGULAR, CYLINDRICAL, SPHERICAL };

//
// Mesh Class
//

class Mesh
{
public: 

	// Constructor
	Mesh();

	// Buffers
	void CreateBuffers();
	void LoadBuffers(uchar renderFlag);

	// Adds a vertex to the array
	int AddVertex(Vertex &v);
	int AddVertex(Real3 position, 
								Real3 normal = Real3(0.0f, 1.0f, 0.0f), 
								Real2 tex = Real2(0.0f, 0.0f));

	// Checks for vertex with same position
	int AddUniqueVertex(Real3 position, 
											Real3 normal = Real3(0.0f, 1.0f, 0.0f), 
											Real2 tex = Real2(0.0f, 0.0f));

	// Adds a triangle to the array
	int AddTriangle(Triangle &t);
	int AddTriangle(uint a, uint b, uint c);
	
	// Adds a quad to the array
	int AddQuad(Quad &q);
	int AddQuad(uint a, uint b, uint c, uint d);

	// Merges the duplicated vertices & corrects the quads & triangles
	void MergeDuplicateVertices();

	// Calculates the vertex normals from the faces
	void CalculateVertexNormals();

	// Calculates vertex texture coordinates from bbox and scale
	void CalculateTextureCoordinates(BBox *box, float scale, TexCoordType type);

	// Clears Data
	void Clear();

	// Clean up all the data
	void CleanUp();

	// Removes the vertex and decreases all indices above its index
	void SafeRemoveVertex(uint i);

	// Calculate BBox
	void CalculateBBox(BBox *box);
	void CalculateBBoxOctree(Entity *e);

	// Rotates all the vertices
	void RotateVertices(const D3DXMATRIX *rotation);

	// Write to file
	void Write(FileStream &file);

	// Read from file
	void Read(FileStream &file);

private:

	// Data
	vector<Vertex> vertices;
	vector<Triangle> triangles;
	vector<Quad> quads;

	// D3D Buffers
	LPDIRECT3DVERTEXBUFFER9 vertexBuffer; 
	LPDIRECT3DINDEXBUFFER9 triangleBuffer; 
	LPDIRECT3DINDEXBUFFER9 quadBuffer; 

	// Update bools
	bool updateVB;
	bool updateTB;
	bool updateQB;

	// Create Buffers
	void CreateVBuffer();
	void CreateTBuffer();
	void CreateQBuffer();

	// Load Buffers
	void LoadVBuffer();
	void LoadTBuffer();
	void LoadQBuffer();

	// All indices above max are decreased by one
	void DecreaseIndices(uint max);

	// Render
	void Render(uchar renderFlag, bool renderTris);

	friend class Geometry;
	friend class SubdivisionGeom;
	friend class TerrainGeom;
	friend class SubLevelGeom;
};

#endif // __MESH_H__